package org.gten.gegedexin.SMTP;

import utils.base64Coder;

import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Base64;


public class SSLEmailSender {

    String enter="\r\n";
    String smtpServer = "aptx_0329";//邮箱名（不用后缀）
    int smtpPort = 465; // Default SMTP SSL/TLS port
    String senderEmail = "aptx_0329@163.com";
    String recipientEmail="321161808@qq.com";
    String subject = "Test";
    String body = "Hello,long time no see.";
    String AuthorizationCode = "MUYETQNJDEACOFDR";
    String ResourcesPathStr = "D:\\JavaCode\\gegedexin\\src\\main\\resources\\7.mp4";
    String MediaType= "1";///octet-stream
    String filename= "77.mp4";
    public SSLEmailSender() {

    }

    public void puretext(OutputStreamWriter writer) throws IOException//纯文本
    {
        writer.write("Content-Type: text/plain; charset=utf-8"+enter);
         //对于每个附件，可以使用7bit，8bit，binary ，quoted-printable，base64和custom中的一种编码方式。
         // 7bit编码是用在US ASCII字符集上的常用的一种编码方式，也就是，保持它的原样。
         // 8bit和binary编码一般不用。
         // 对人类可读的标准文本，如果传输要经过对格式有影响的网关时对其进行保护，可以使用quoted printable。
         // Base64是一种通用方法，在需要决定使用哪一种编码方法时，它提供了一个不用费脑子的选择；它通常用在二进制，非文本数据上。
        writer.write(enter);//不能省略
        writer.write(body+enter);
        writer.write(enter);
    }
    public void appendix(OutputStreamWriter writer,String MediaType) throws IOException //附件
    {
        Path ResourcesPath = Paths.get(ResourcesPathStr);
        byte[] MediaData = Files.readAllBytes(ResourcesPath);
        String encodedMedia = Base64.getEncoder().encodeToString(MediaData);

        String mediaType=MediaType;//临时变量
        writer.write("Content-Type:"+mediaType+enter);//文件类型
        writer.write("Content-Transfer-Encoding: base64"+enter);//编码方式
        writer.write("Content-Disposition: attachment; filename=\""+filename+"\""+enter);//附件发送

        writer.write(enter);//不能省略
        writer.write(encodedMedia+enter);
        writer.write(enter);//不能省略
    }
    public void oversizedAppendix(OutputStreamWriter writer) throws IOException //超大附件
    {

        Path ResourcesPath = Paths.get(ResourcesPathStr);
        byte[] MediaData = Files.readAllBytes(ResourcesPath);
        String encodedMedia = Base64.getEncoder().encodeToString(MediaData);

        writer.write("Content-Type:application/octet-stream"+enter);//文件类型
        writer.write("Content-Transfer-Encoding: base64"+enter);//编码方式
        writer.write("Content-Disposition: attachment; filename=\""+filename+"\""+enter);//附件发送

        writer.write(enter);
        int chunkSize = 1024; // Adjust the chunk size as per your requirements
        for (int i = 0; i < encodedMedia.length(); i += chunkSize) {
            int endIndex = Math.min(i + chunkSize, encodedMedia.length());
            String chunk = encodedMedia.substring(i, endIndex);
            writer.write(chunk + enter);
        }
        writer.write(enter);
    }

    public void send(String host) throws Exception {

        //建立连接
        SSLSocketFactory sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
        SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(host, smtpPort);
        InputStream is = socket.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"));
        OutputStream os = socket.getOutputStream();
        OutputStreamWriter writer = new OutputStreamWriter(os, "gbk");

        //指定信息
        writer.write("EHLO "+smtpServer+enter);//邮箱名（不用后缀）
        writer.write("STARTTLS "+enter);
        socket.startHandshake();

        writer.write("EHLO "+smtpServer+enter);
        writer.write("auth login"+enter);
        writer.write(base64Coder.Encoder(senderEmail)+enter);//邮件名和后缀的base64加密字符串
        writer.write(base64Coder.Encoder(AuthorizationCode)+enter);//邮箱授权码的base64加密字符串
        writer.write("MAIL FROM:<"+senderEmail+">"+enter);
        writer.write("RCPT TO: <" + recipientEmail + ">"+enter);	// 确认接收者
        writer.write("DATA"+enter);

        //开始发送
        writer.write("from:<"+senderEmail+">"+enter);
        writer.write("to:<"+recipientEmail+">"+enter);
        writer.write("subject:"+subject+enter);
        writer.write("MIME-Version: 1.0"+enter);


        switch (MediaType)
        {
            case "0"://纯文本
            {
                puretext(writer);
                break;
            }
            case "1"://超大附件、video
            {
                oversizedAppendix(writer);
                break;
            }

            case "multipart/mixed"://混合,表示文档的多个部分是混合的，指正文与附件的关系。
            {
                String boundary = "====JavaMIMEBoundary====";
                writer.write("Content-Type:"+MediaType+";boundary="+boundary+enter);//文件类型

                writer.write(enter);

                //开始分part的内容
                writer.write("--" + boundary+enter);
                puretext(writer);

                //添加附件
                writer.write("--" + boundary+enter);
                appendix(writer,"image");

                //结束
                writer.write("--" + boundary + "--"+enter);

                break;
            }
//            case "multipart/related"://关联,表示文档的多个部分是相关的，一般用来描述Html正文与其相关的图片
//            {
//                //未实现
//                break;
//            }
//            case "multipart/alternative"://选择,表示正文由两个部分组成，可以选择其中的任意一个
//            {
//                //未实现
//                break;
//            }

            default://"text","image","audio","application"
            {
                appendix(writer,MediaType);
                break;
            }

        }

        //发送结束
        writer.write(enter+"."+enter);
        writer.write("QUIT"+enter);
        writer.flush();

        // 读取回传的信息
        String line;
        while((line=reader.readLine()) != null) {
            System.out.println(line);
        }

        socket.close();
    }

    public void sendText(String title,String text) throws Exception {
        subject = title;
        body = text;
        MediaType = "0";
        send("smtp.163.com");
    }

    public void sendAppendix(String title,String filePath,String fileName) throws Exception {
        subject = title;
        ResourcesPathStr = filePath;
        filename = fileName;
        MediaType = "1";
        send("smtp.163.com");
    }
}
